# -*-coding:utf-8 -*-
from tree_sitter import Language, Parser
import re
import process_file as pf
from copy import deepcopy  # 深拷贝用于生成新节点
SO_PATH = '../build-rust/librust.so'

def print_ast(node, indent=0):
    print(' ' * indent + f'{node.type}: {node.text.decode("utf-8") if node.text else ""}')
    for child in node.children:
        print_ast(child, indent + 2)

def get_root_node(code):
    LANGUAGE = Language(SO_PATH, 'rust')  # 确保路径和文件名正确
    parser = Parser()
    parser.set_language(LANGUAGE)

    # 解析代码生成语法树
    tree = parser.parse(bytes(code, "utf8"))
    root_node = tree.root_node
    return root_node



def remove_emptylines_comments_attributes(rust_code: str) -> str:
    """
    删除 Rust 代码中的所有空行和注释（包括单行注释和多行注释）。

    :param rust_code: Rust 代码字符串
    :return: 删除空行和注释后的代码
    """
    lines = rust_code.splitlines()  # 将代码按行分割
    cleaned_lines = []
    in_block_comment = False  # 标记是否在多行注释块中

    for line in lines:
        stripped_line = line.strip()
        if "#" in stripped_line:
            continue


        # 处理多行注释
        if in_block_comment:
            if '*/' in stripped_line:
                in_block_comment = False
                # 去除多行注释结束符后的内容
                stripped_line = stripped_line.split('*/', 1)[1].strip()
            else:
                continue  # 忽略多行注释中的内容

        # 处理单行注释
        if '//' in stripped_line:
            stripped_line = stripped_line.split('//', 1)[0].strip()

        # 处理多行注释开始
        if '/*' in stripped_line:
            in_block_comment = True
            # 去除多行注释开始符前的代码
            stripped_line = stripped_line.split('/*', 1)[0].strip()

        # 如果行不为空，则添加到结果中
        if stripped_line:
            cleaned_lines.append(line)

    # 将处理后的行拼接为字符串
    return '\n'.join(cleaned_lines)












def get_function_name(function_node):
    name_node = function_node.child_by_field_name('name')
    function_name = name_node.text.decode('utf-8') if name_node else None
    return function_name


'''
0228 update
适用于FUT不适用TF(TF的assert修改过)
'''
def function_str_to_node(root_node, target_function):
    # 使用栈实现非递归遍历
    stack = [root_node]
    while stack:
        node = stack.pop()
        # 如果当前节点是函数定义
        if node.type == "function_item":
            # 获取函数的源代码
            function_code = node.text.decode("utf8")
            # 如果匹配目标函数内容
            if function_code.strip() == target_function.strip():
                return node
        # 将子节点压入栈中
        stack.extend(node.children)
    return None

def function_name_to_node(root_node, target_func_name):
    # 使用栈实现非递归遍历
    stack = [root_node]
    while stack:
        node = stack.pop()
        # 如果当前节点是函数定义
        if node.type == "function_item":
            # 获取函数的源代码
            function_name = get_function_name(node)
            if function_name == target_func_name:
                return node
        # 将子节点压入栈中
        stack.extend(node.children)
    return None




def find_nth_substr_next_char(s, substr, n):
    # 记录找到的子字符串的数量
    count = 0
    # 从字符串的起始位置开始查找
    pos = 0

    while count < n:
        # 查找substr的位置
        pos = s.find(substr, pos)

        # 如果找不到子字符串，返回空字符串
        if pos == -1:
            return "", -1  # 没有找到时返回空字符串和-1

        # 找到一个匹配的子字符串，计数加1
        count += 1

        # 如果找到了第n个匹配，返回它后面的字符
        if count == n:
            # 如果子字符串后面没有字符，则返回空字符串和-1
            if pos + len(substr) >= len(s):
                return "", -1
            else:
                # 返回字符及其下标
                return s[pos + len(substr)], pos + len(substr)

        # 更新pos，继续查找下一个
        pos += len(substr)

    return "", -1  # 如果没有找到第n个子字符串，返回空字符串和-1



'''
从给定的起始下标开始，提取括号内的内容，支持括号嵌套。
start_index为"("的位置
'''
def get_content_in_parentheses(start_index, input_str):

    # 确保开始位置是 '('
    if input_str[start_index] != '(':
        print(f"11111{input_str[start_index:]}")
        raise ValueError("The character at the given index is not '('.")

    # 初始化变量
    depth = 1  # 当前括号深度，已知当前位置是 '('，所以深度从 1 开始
    end_index = start_index + 1  # 从 '(' 后面开始查找
    content = "("  # 把 '(' 加入到结果中

    # 遍历直到找到匹配的 ')'
    while depth > 0 and end_index < len(input_str):
        char = input_str[end_index]
        content += char  # 将当前字符加入内容

        if char == '(':
            depth += 1  # 遇到 '('，深度加 1
        elif char == ')':
            depth -= 1  # 遇到 ')'，深度减 1

        end_index += 1

    if depth > 0:
        # 括号补全
        content += depth * ')'

    return content

"""
计算括号内的参数数量，忽略括号、花括号、方括号和引号内的逗号。

参数：
s: str，输入的字符串，必须以 '(' 开头，')' 结尾。

返回：
int，括号内的有效参数数量。
"""
def get_para_num_in_parentheses(s):

    if not (s.startswith('(') and s.endswith(')')):
        raise ValueError("Input string must start with '(' and end with ')'.")

    # 去掉外层的括号
    s = s[1:-1]
    if not s.strip():
        return 0

    # 初始化栈和计数器
    stack = []
    parameter_count = 0
    in_quotes = False  # 标记是否在字符串引号内
    quote_char = None  # 引号的种类，可以是单引号或双引号

    i = 0
    while i < len(s):
        char = s[i]

        # 处理引号内的内容
        if char == '"' or char == "'":
            if in_quotes:
                if char == quote_char:
                    in_quotes = False
            else:
                in_quotes = True
                quote_char = char

        # 处理括号和花括号
        elif char in '({[<':
            stack.append(char)  # 进入一个新的括号或花括号内
        elif char in ')}]>':
            if stack:
                stack.pop()  # 退出当前的括号或花括号

        # 计数有效的逗号
        elif char == ',':
            # 只有当栈为空且不在引号内时，逗号才算作分隔符
            if not stack and not in_quotes:
                parameter_count += 1

        i += 1

    # 最后一个参数没有逗号，因此加 1
    return parameter_count + 1


def get_list_name_and_paranum(root_node, rust_code, dict_substr_num):
    result = []

    # 遍历 AST，查找 identifier 类型的节点
    for child in root_node.children:
        if child.type == 'identifier':
            func_name = child.text.decode("utf8")
            if func_name not in dict_substr_num:
                dict_substr_num[func_name] = 1
            else:
                dict_substr_num[func_name] += 1

            # 找到child下一个字节内容
            next_byte, index = find_nth_substr_next_char(rust_code, func_name, dict_substr_num[func_name])
            if next_byte == '(':
                content = get_content_in_parentheses(index, rust_code)
                cnt = get_para_num_in_parentheses(content)
                # print(f"{func_name}, {content}, {cnt}")
                result.append((func_name, cnt))

        # 递归查找子节点
        result.extend(get_list_name_and_paranum(child, rust_code, dict_substr_num))

    return result



'''
返回#[test]的数量
'''
def get_test_num(root_node):
    # 用来计数满足条件的子节点
    count = 0

    for i, child in enumerate(root_node.children):
        # 如果满足条件，进行计数
        if child.type == 'attribute_item' and child.text.decode('utf-8') == '#[test]':
            # 找到#[test]下方的第一个函数
            while i < len(root_node.children) and root_node.children[i].type != 'function_item':
                i += 1
            if i >= len(root_node.children):
                continue
            # 找到测试函数
            # function_name = get_function_name(root_node.children[i])
            # list_total_name.append(function_name)
            # if "test" in function_name:
            #     list_include_test_name.append(function_name)
            # print(root_node.children[i].text.decode('utf-8'))

            count += 1  # 增加计数

        # 递归调用，累加子节点的计数
        count += get_test_num(child)

    return count  # 返回当前节点及其子树中符合条件的子节点数量



def get_list_node_test_function(root_node):
    list_node_test_function = []

    for i, child in enumerate(root_node.children):
        # 如果满足条件，搜集符合条件的function_item节点
        if child.type == 'attribute_item' and child.text.decode('utf-8') == '#[test]':
            # 找到#[test]下方的第一个函数
            while i < len(root_node.children) and root_node.children[i].type != 'function_item':
                i += 1
            if i >= len(root_node.children):
                continue
            # 找到测试函数
            function_node = root_node.children[i]
            list_node_test_function.append(function_node)

        # 递归调用，搜集子节点中的符合条件的节点
        list_node_test_function.extend(get_list_node_test_function(child))

    return list_node_test_function  # 返回搜集到的所有符合条件的function_item节点


"""
返回包含所有断言语句的列表
"""
def get_list_node_assert(function_node):
    assertions = []
    for child in function_node.children:
        # 检查是否是宏调用，并且包含常见断言宏
        if child.type == 'macro_invocation':
            macro_text = child.text.decode('utf-8')
            if any(assertion in macro_text for assertion in ['assert!', 'assert_eq!', 'assert_ne!']):
                assertions.append(child)  # 添加节点而不是文本

        # 递归检查子节点并将结果添加到列表中
        assertions.extend(get_list_node_assert(child))

    return assertions





def get_first_node_assert(function_node):
    for child in function_node.children:
        # 检查是否是宏调用，并且包含常见断言宏
        if child.type == 'macro_invocation':
            macro_text = child.text.decode('utf-8')
            if any(assertion in macro_text for assertion in ['assert!', 'assert_eq!', 'assert_ne!']):
                return child
        result = get_first_node_assert(child)
        if result:
            return result
    return None



def complete_function_right_brace_with_indent(truncated_function):
    # 计算函数中的左大括号和右大括号的数量
    open_brace_count = truncated_function.count('{')
    close_brace_count = truncated_function.count('}')

    # 如果左大括号比右大括号多，则需要补充右大括号
    if open_brace_count > close_brace_count:
        missing_right_braces = open_brace_count - close_brace_count

        # 逆向遍历补充右大括号，并计算每个大括号的缩进
        result = truncated_function
        lines = truncated_function.split('\n')  # 按行拆分函数

        indent_level = 0  # 最后的 `}` 缩进是 0

        for i in range(missing_right_braces):
            # 对每个缺失的 `}` 增加对应的缩进
            result += '\n' + (' ' * 4 * (missing_right_braces - 1 - i) + '}')

        return result
    return truncated_function


# def remove_lines_containing_substring(input_str, substring):
#     # 将输入字符串按行拆分成列表
#     lines = input_str.split('\n')
#     for line in lines:
#         if substring in line:
#
#
#     # 使用列表推导式过滤掉包含子字符串的行
#     filtered_lines = [line for line in lines if substring not in line]
#
#     # 将剩下的行重新合并为一个字符串
#     return '\n'.join(filtered_lines)



def remove_first_line_containing_substring(input_str, substring):
    # 将输入字符串按行拆分成列表
    lines = input_str.split('\n')

    # 标志变量，用于记录是否已经删除过目标行
    removed = False
    filtered_lines = []

    # 遍历行并过滤
    for line in lines:
        if not removed and substring in line:
            # 跳过当前行并将标志设为True
            removed = True
        else:
            # 保留其他行
            filtered_lines.append(line)

    # 将剩下的行重新合并为一个字符串
    return '\n'.join(filtered_lines)



def get_list_node_function_by_assert(function_node):
    rust_code = function_node.text.decode('utf-8')
    list_node_assert = get_list_node_assert(function_node)
    list_code_remove_assert = []
    list_node_function_by_assert = []
    current_position = 0  # 跟踪当前的处理位置

    for node_assert in list_node_assert:
        assert_code = node_assert.text.decode('utf-8')

        # 从当前处理位置开始查找 assert_code 的位置
        start_index = rust_code.find(assert_code, current_position)
        if start_index == -1:
            continue  # 如果未找到，跳过当前 assert 语句

        end_index = start_index + len(assert_code)
        function_by_assert = rust_code[:end_index] + ';'

        # 更新当前处理位置，避免重复使用同一个 assert 的位置
        current_position = end_index

        # 删除其他 assert 语句
        for code_remove_assert in list_code_remove_assert:
            function_by_assert = remove_first_line_containing_substring(function_by_assert, code_remove_assert)
        list_code_remove_assert.append(assert_code)

        # 补全右括号
        function_by_assert = complete_function_right_brace_with_indent(function_by_assert)

        # 再转为 function_node
        root_node = get_root_node(function_by_assert)
        node_function_by_assert = get_first_node_function(root_node)
        list_node_function_by_assert.append(node_function_by_assert)

    return list_node_function_by_assert










'''
function: 结果存储在function_items中，为函数节点
input: rs文件的root_node, 一个空列表function_items
可通过len(function_items)直接计算rs文件中的函数数量
'''
def get_list_node_total_function(root_node):
    list_total_function = []

    for child in root_node.children:
        if child.type == 'function_item':
            list_total_function.append(child)

        # 递归调用并使用extend将子树的结果合并
        list_total_function.extend(get_list_node_total_function(child))

    return list_total_function


'''
适用于确定只有一个函数的节点
'''
def get_first_node_function(root_node):
    # 遍历当前节点的所有子节点
    for child in root_node.children:
        if child.type == 'function_item':
            return child  # 找到第一个 function_item 节点后直接返回

        # 递归检查子节点
        result = get_first_node_function(child)
        if result:  # 如果递归返回了结果，直接返回
            return result
    return None  # 如果没有找到任何 function_item 节点，返回 None



'''
function: 返回一个列表，列表里的元素为function_item节点，且所有节点的(函数名, 参数数量)不重复
'''
def get_list_unique_node_function_item(list_node_function_item):
    # 创建一个字典来记录函数名和参数数量的出现次数
    dict_name_and_cnt_parameters = {}

    # 遍历 function_items，填充 count_dict
    for node_function_item in list_node_function_item:
        node_function_name = node_function_item.child_by_field_name('name')
        str_function_name = node_function_name.text.decode('utf-8') if node_function_name else None
        node_parameters = node_function_item.child_by_field_name('parameters')
        # str_parameters 格式：(&mut self, iterable: I)
        str_parameters = node_parameters.text.decode('utf-8') if node_parameters else None
        cnt_parameters = pf.count_parameters(str_parameters)
        key = (str_function_name, cnt_parameters)

        if key in dict_name_and_cnt_parameters:
            dict_name_and_cnt_parameters[key] += 1
        else:
            dict_name_and_cnt_parameters[key] = 1

    list_unique_node_function_item = []
    for node_function_item in list_node_function_item:
        node_function_name = node_function_item.child_by_field_name('name')
        str_function_name = node_function_name.text.decode('utf-8') if node_function_name else None
        node_parameters = node_function_item.child_by_field_name('parameters')
        # str_parameters 格式：(&mut self, iterable: I)
        str_parameters = node_parameters.text.decode('utf-8') if node_parameters else None
        cnt_parameters = pf.count_parameters(str_parameters)

        if dict_name_and_cnt_parameters[(str_function_name, cnt_parameters)] == 1:
            list_unique_node_function_item.append(node_function_item)
        # else:
        #     print(str_function_name, cnt_parameters)
    return list_unique_node_function_item


'''
key为（函数名，参数数量）
value为node_function_item
删除key重复的所有{key:value}
'''
def get_dict_unique_node_function_item(list_node_function_item):
    # 创建一个字典来记录函数名和参数数量的对应的 function_item
    dict_function_items = {}
    # 创建一个集合来记录重复的键
    duplicate_keys = set()

    # 遍历 function_items，填充 dict_function_items
    for node_function_item in list_node_function_item:
        node_function_name = node_function_item.child_by_field_name('name')
        str_function_name = node_function_name.text.decode('utf-8') if node_function_name else None
        node_parameters = node_function_item.child_by_field_name('parameters')
        str_parameters = node_parameters.text.decode('utf-8') if node_parameters else None
        cnt_parameters = pf.count_parameters(str_parameters)
        key = (str_function_name, cnt_parameters)

        # 检查键是否已存在
        if key in dict_function_items:
            # 如果存在，则标记为重复
            duplicate_keys.add(key)
        else:
            dict_function_items[key] = node_function_item

    # 从字典中移除所有重复的键
    for key in duplicate_keys:
        if key in dict_function_items:
            del dict_function_items[key]

    return dict_function_items




'''
key为（函数名，参数数量）
value为node_function_item
key重复保留一个{key:value}
'''
def get_dict_not_unique_node_function_item(list_node_function_item):
    # 创建一个字典来记录函数名和参数数量的对应的 function_item
    dict_function_items = {}
    # 创建一个集合来记录重复的键
    duplicate_keys = set()

    # 遍历 function_items，填充 dict_function_items
    for node_function_item in list_node_function_item:
        node_function_name = node_function_item.child_by_field_name('name')
        str_function_name = node_function_name.text.decode('utf-8') if node_function_name else None
        node_parameters = node_function_item.child_by_field_name('parameters')
        str_parameters = node_parameters.text.decode('utf-8') if node_parameters else None
        cnt_parameters = pf.count_parameters(str_parameters)
        key = (str_function_name, cnt_parameters)

        dict_function_items[key] = node_function_item

    return dict_function_items




'''
0228 update
支持任意一个函数节点, 返回的也是node类型
'''
def get_node_function_parent(node_func):
    parent_item = node_func.parent

    while parent_item is not None:
        if parent_item.type in {'struct_item', 'trait_item', 'impl_item', 'module', 'mod_item'}:
            return parent_item
        parent_item = parent_item.parent
    return None


def get_function_parent(functon_node):
    function_parent = ''
    node_function_parent = get_node_function_parent(functon_node)
    if node_function_parent:
        function_parent = node_function_parent.text.decode('utf-8')
    return function_parent

"""
提取函数节点中的函数名、参数列表、参数个数、返回类型、完整函数、父节点信息
"""
def get_dict_function_info(function_node):
    param_nums = 0

    # 获取函数名
    name_node = function_node.child_by_field_name('name')
    function_name = name_node.text.decode('utf-8') if name_node else None
    # 获取参数列表
    params_node = function_node.child_by_field_name('parameters')
    parameters = []
    if params_node:
        for param in params_node.children:
            if param.type == 'parameter':
                param_nums += 1
                parameters.append(param.text.decode('utf-8'))
    # 获取返回类型
    return_type_node = function_node.child_by_field_name('return_type')
    return_type = return_type_node.text.decode('utf-8') if return_type_node else "None"
    # 获取完整函数
    full_function = function_node.text.decode('utf-8') if function_node.text else None

    # 获取parent
    fn_parent = ''
    node_fn_parant = get_node_function_parent(function_node)
    if node_fn_parant:
        fn_parent = node_fn_parant.text.decode('utf-8')

    return {
        'FUT_name': function_name,
        'FUT_para_list': parameters,
        'FUT_para_count': param_nums,
        'FUT_return_type': return_type,
        'FUT_full': full_function,
        'FUT_parent': fn_parent
    }



def get_function_para_count(function_node):
    para_num = 0
    node_para = function_node.child_by_field_name('parameters')
    if node_para:
        for node in node_para.children:
            if node.type == 'parameter':
                para_num += 1
    return para_num

def get_function_para_list(function_node):
    list_para = []
    node_para = function_node.child_by_field_name('parameters')
    if node_para:
        for node in node_para.children:
            if node.type == 'parameter':
                list_para.append(node.text.decode('utf-8'))
    return list_para


def get_function_return_type(function_node):
    return_type_node = function_node.child_by_field_name('return_type')
    return_type = return_type_node.text.decode('utf-8') if return_type_node else "None"
    return return_type






'''
提取所有函数名、参数和返回类型
input: get_root_node(rust_code)
output: list of dict，包含函数名、参数和返回类型
'''
def extract_function_details(node):
    functions = []
    # 遍历节点
    for child in node.children:
        # 检查节点类型
        if child.type == 'function_item':  # Rust 中的函数定义类型
            functions.append(get_dict_function_info(child))  # 调用独立的函数信息提取函数

        # 递归提取子节点
        functions.extend(extract_function_details(child))
    return functions


"""
递归检查是否包含断言语句（assert!、assert_eq!、assert_ne!）
用法：
if child.type == 'function_item':
     if(is_contains_assertion(child)):
"""
def is_contains_assertion(node):
    for child in node.children:
        # 检查是否是宏调用，并且文本包含常见断言宏
        if child.type == 'macro_invocation' and child.text:
            macro_text = child.text.decode('utf-8')
            if any(assertion in macro_text for assertion in ['assert!', 'assert_eq!', 'assert_ne!']):
                return True
        # 递归检查子节点
        if is_contains_assertion(child):
            return True
    return False


def find_variable_declaration(root_node, variable_name):
    results = []  # 初始化结果列表

    # 遍历节点
    for child in root_node.children:
        # 检查是否是 let_declaration
        if child.type == 'let_declaration':
            # 查找子节点中的 identifier
            for grandchild in child.children:
                if grandchild.type == 'identifier' and grandchild.text.decode() == variable_name:
                    results.append(child)  # 找到后添加到结果列表

        # 递归查找子节点
        results.extend(find_variable_declaration(child, variable_name))  # 合并结果

    return results  # 返回所有找到的结果


"""
从一个表达式节点中提取变量和函数名
"""
def extract_identifiers_from_expression(expression_node):

    identifiers = []
    # 遍历节点，寻找 identifier 和函数调用
    for child in expression_node.children:
        if child.type == 'identifier':  # 变量或函数名的标识符
            identifiers.append(child.text.decode('utf-8'))
        elif child.type == 'call_expression':  # 函数调用表达式
            function_name = child.child_by_field_name('function')
            if function_name and function_name.type == 'identifier':
                identifiers.append(function_name.text.decode('utf-8'))
        # 递归提取子节点中的标识符
        identifiers.extend(extract_identifiers_from_expression(child))
    return identifiers


def get_identifiers_from_node(node):
    identifiers = []
    for child in node.children:
        if child.type == 'identifier':  # 变量或函数名的标识符
            identifiers.append(child.text.decode('utf-8'))
        identifiers.extend(get_identifiers_from_node(child))
    return identifiers



'''
function: 返回的结果存在result_list中，为所有call_expression节点
'''
def get_node_used_function(statement_node, result_list, root_node, visited_nodes=set()):
    # 检查是否已经处理过这个节点
    if id(statement_node) in visited_nodes:
        return result_list
    visited_nodes.add(id(statement_node))

    # 检查是否是函数调用表达式
    if statement_node.type == 'call_expression':
        result_list.append(statement_node)

    # 遍历节点，查找变量
    for child in statement_node.children:
        if child.type == 'identifier':
            variable_name = child.text.decode('utf-8')
            # print(variable_name)
            # 查找距离当前assert语句最近的变量定义语句
            list_variable_declaration = find_variable_declaration(root_node, variable_name)
            if list_variable_declaration:

                # 找到距离statement_node最近的variable_declaration
                variable_declaration = list_variable_declaration[0]
                for vd in list_variable_declaration:
                    if vd.start_point < statement_node.start_point:
                        variable_declaration = vd
                    else:
                        break

                # 递归调用查找定义中的调用
                get_node_used_function(variable_declaration, result_list, root_node, visited_nodes)
        else:
            # 递归调用处理其他类型的子节点
            get_node_used_function(child, result_list, root_node, visited_nodes)

    return result_list



'''
chatgpt对get_node_used_function函数的优化
'''
# def get_node_used_function(statement_node, result_list, root_node, visited_nodes=set()):
#     # 检查是否已经处理过这个节点
#     if id(statement_node) in visited_nodes:
#         return result_list
#     visited_nodes.add(id(statement_node))
#
#     # 检查是否是函数调用表达式
#     if statement_node.type == 'call_expression':
#         result_list.append(statement_node)
#
#     # 遍历子节点，查找变量
#     for child in statement_node.children:
#         if child.type == 'identifier':
#             variable_name = child.text.decode('utf-8')
#
#             # 查找变量定义
#             list_variable_declaration = find_variable_declaration(root_node, variable_name)
#             if list_variable_declaration:
#                 # 找到距离当前语句最近的变量定义
#                 variable_declaration = list_variable_declaration[0]
#                 for vd in list_variable_declaration:
#                     if vd.start_point < statement_node.start_point:
#                         variable_declaration = vd
#                     else:
#                         break
#
#                 # 递归查找定义中的调用
#                 get_node_used_function(variable_declaration, result_list, root_node, visited_nodes)
#         else:
#             # 递归处理其他类型的子节点
#             get_node_used_function(child, result_list, root_node, visited_nodes)
#
#     return result_list




'''
参数可以是任意node
'''
def get_list_node_call_expression(node):
    list_node_call_expression = []
    for child in node.children:
        if child.type == 'call_expression':
            list_node_call_expression.append(child)
        list_node_call_expression.extend(get_list_node_call_expression(child))
    return list_node_call_expression






def get_list_name_and_paranum(root_node, rust_code, dict_substr_num):
    result = []

    # 遍历 AST，查找 identifier 类型的节点
    for child in root_node.children:
        if child.type == 'identifier':
            func_name = child.text.decode("utf8")
            if func_name not in dict_substr_num:
                dict_substr_num[func_name] = 1
            else:
                dict_substr_num[func_name] += 1

            # 找到child下一个字节内容
            next_byte, index = find_nth_substr_next_char(rust_code, func_name, dict_substr_num[func_name])
            if next_byte == '(':
                content = get_content_in_parentheses(index, rust_code)
                cnt = get_para_num_in_parentheses(content)
                # print(f"{func_name}, {content}, {cnt}")
                result.append((func_name, cnt))

        # 递归查找子节点
        result.extend(get_list_name_and_paranum(child, rust_code, dict_substr_num))

    return result



'''
没有使用tree-sitter
0301 update
原先得到的name取最后一个"."之后的字符作为结果 如self.bucket_array_ref --> bucket_array_ref
'''
def get_call_expression_name(call_expression_node):
    str_call_expression = call_expression_node.text.decode('utf-8')

    end_index = str_call_expression.find('(')
    # 没有找到左括号，返回空字符串
    if end_index == -1:
        return ''

    # 尖括号栈
    stack_angle_bracket = 0
    index = end_index - 1
    while index >= 0:
        if str_call_expression[index] == '>':
            stack_angle_bracket += 1
            index -= 1
            while stack_angle_bracket and index >= 0:
                if str_call_expression[index] == '>':
                    stack_angle_bracket += 1
                elif str_call_expression[index] == '<':
                    stack_angle_bracket -= 1
                index -= 1
            # 去掉<前的::，确保index不越界
            while index >= 0 and str_call_expression[index] == ':':
                index -= 1
            end_index = index + 1
            continue

        if str_call_expression[index] == ':':
            start_index = index + 1
            break
        index -= 1
    else:
        start_index = 0  # 如果没有找到冒号，则从开始位置开始
    return str_call_expression[start_index:end_index].strip().split('.')[-1]



def get_call_expression_argument_count(call_expression_node):
    arguments_node = call_expression_node.child_by_field_name("arguments")

    if arguments_node:
        return sum(
            1 for child in arguments_node.children
            if child.type not in {'(', ')', ','}  # Exclude parentheses and commas
        )
    return 0


    # argument_count = len(arguments_node.children) if arguments_node else 0
    # return argument_count




'''
0228 add
找到函数调用了哪些函数
dict_node_func:{(name_func, cnt_para_num): node_func}
'''
def get_dict_func_call_ex(node_func, dict_node_func):
    dict_func_call_ex = {}
    list_node_call_ex = get_list_node_call_expression(node_func)
    for node_call_ex in list_node_call_ex:
        name_call_ex = get_call_expression_name(node_call_ex)
        cnt_para_call_ex = get_call_expression_argument_count(node_call_ex)
        if (name_call_ex, cnt_para_call_ex) in dict_node_func:
            dict_func_call_ex[(name_call_ex, cnt_para_call_ex)] = dict_node_func[(name_call_ex, cnt_para_call_ex)]
    return dict_func_call_ex


'''
0228 add
找到哪些函数调用了目标函数（调用FUT的函数）
dict_node_func:{(name_func, cnt_para_num): node_func}
'''
def get_dict_call_ex_func_target(node_func_target, dict_node_func):
    dict_call_ex_func_target = {}
    # 找到node_func_target的(name_func, cnt_para_num)
    node_name_func = node_func_target.child_by_field_name('name')
    name_func = node_name_func.text.decode('utf-8') if node_name_func else None
    node_para = node_func_target.child_by_field_name('parameters')
    cnt_para_num = pf.count_parameters(node_para.text.decode('utf-8') if node_para else None)
    key_func_target = (name_func, cnt_para_num)

    # 遍历dict_node_func的value(node)，判断这些函数有没有调用func_target
    for key_func, value_func in dict_node_func.items():
        list_node_call_ex = get_list_node_call_expression(value_func)
        for node_call_ex in list_node_call_ex:
            name_call_ex = get_call_expression_name(node_call_ex)
            cnt_para_call_ex = get_call_expression_argument_count(node_call_ex)
            if (name_call_ex, cnt_para_call_ex) == key_func_target:
                dict_call_ex_func_target[key_func] = value_func
                break
    return dict_call_ex_func_target


'''
0301 update
返回压缩后的函数（字符串类型）
如 pub fn example(){}
'''
def func_compress(node_func):
    str_func = node_func.text.decode('utf-8')
    # name_func = get_function_name(node_func)

    parts = str_func.split('{', 1)  # 只分割一次
    str_func_simplify = str_func
    if len(parts) > 1:
        str_func_simplify = parts[0] + '{}'
    return str_func_simplify









'''
0303 update
返回压缩后的函数（字符串类型）
参数为字符串类型的函数
'''
def func_str_compress(str_func):
    parts = str_func.split('{', 1)
    str_func_simplify = str_func
    if len(parts) > 1:
        str_func_simplify = parts[0] + '{}'
    return str_func_simplify


def str_compress(str):
    root_node = get_root_node(str)
    str_simplify = str
    list_node_total_function = get_list_node_total_function(root_node)
    for node_func in list_node_total_function:
        str_func = node_func.text.decode('utf-8')
        str_func_simplify = func_compress(node_func)
        str_simplify = str_simplify.replace(str_func, str_func_simplify)
    str_simplify = remove_emptylines_comments_attributes(str_simplify)
    return str_simplify
    













